from flask import Flask, jsonify, request
from flask_cors import CORS # 处理跨域问题
import sqlite3 # 数据库模块
import os

# app - 这是创建的Flask应用实例，后面所有的路由配置、请求处理都会基于这个实例
# __name__ - 这是Python的特殊变量，表示当前模块的名称 ，如果这个模块被直接运行，那么__name__的值就是__main__，如果这个模块是被其他模块导入的，那么__name__的值就是模块的名字
app = Flask(__name__) # 创建一个Flask应用实例 是falsk框架的核心类 用于创建一个web应用

CORS(app) # 处理跨域问题

DATABASE = 'test.db' # 数据库文件路径

def get_db_connection():
  """获取数据库连接"""
  conn = sqlite3.connect(DATABASE)
  # 默认情况 游标返回的结果是元组类型 不方便使用 所以将其转换为字典类型
  conn.row_factory = sqlite3.Row # 将查询结果转换为字典类型 使返回结果像字典一样可访问
  return conn

def init_db():
  """初始化数据和表"""
  # os.path.exists()是Python标准库中的函数，用于检查指定路径的文件或目录是否存在
  if not os.path.exists(DATABASE): # 如果数据库文件不存在，就创建新的数据库并初始化表结构
    conn = get_db_connection() # 获取数据库连接对象

    # 创建游标对象
    cursor = conn.cursor() # 游标是数据库中操作的核心工具 用于执行SQL语句 通过游标可以执行查询、插入、更新、删除

    # 创建表 执行了一个SQL语句，创建了一个名为users的表
    # 这个不是固定模板，而是自定义的表结构设计
    # CREATE TABLE IF NOT EXISTS - 这是SQL标准语法（如果表不存在就创建）
    # '''.... ''' 三单引号表示多行字符串，可以用来写多行SQL语句
    cursor.execute('''
    CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY AUTOINCREMENT,  # 主键自增
        name TEXT NOT NULL, # 用户名 不能为空
        age INTEGER, # 年龄 可以为空
        email TEXT # 邮箱 可以为空
    )
    ''')

    # 插入示例数据
    samples_users = [
      ('这是后端请求的数据', 25, 'zhangsan@example.com'),
      ('李四', 30, 'lisi@example.com'),
      ('王五', 28, 'wangwu@example.com')
    ]
    # 执行批量插入操作
    # execute() - 执行单条SQL语句
    # executemany() - 执行多条SQL语句 批量插入数据
    # INSERT INTO users (name, age, email) - 向users表的指定字段插入数据
    # VALUES (?, ?, ?) - 使用占位符?，防止SQL注入攻击
    cursor.executemany('INSERT INTO users (name, age, email) VALUES (?, ?, ?)', samples_users)

    conn.commit() # 提交事务 使更改生效

    conn.close() # 关闭数据库连接

    print('数据库初始化完成')


# API 路由

@app.route('/api/users', methods=['GET'])
def get_all_users():
  """获取所有用户"""
  conn = get_db_connection() # 获取数据库连接
  cursor = conn.cursor() # 获取游标对象

  # SELECT * 查询所有字段 可以改成具体字段 如：SELECT name, age, email
  # FROM users - 查询users表
  # ORDER BY created_at DESC - 按照创建时间降序排序
  cursor.execute('SELECT * FROM users ORDER BY age DESC') # 执行SQL查询语句 查询所有用户数据 并按照时间降序排序

  # 如果是逻辑删除 只查询未删除的用户 WHERE is_deleted = 0
  # cursor.execute('SELECT * FROM users WHERE is_deleted = 0 ORDER BY age DESC')

  users = cursor.fetchall() # 获取所有查询结果
  conn.close() # 关闭数据库连接

  # 将查询结果转换为字典列表
  # Flask的jsonify()需要字典格式才能正确转换JSON
  users_list = [dict(user) for user in users]
  print(users_list)
 
  return jsonify(users_list) # 返回JSON格式的响应

@app.route('/api/add_user', methods=['POST'])
def create_user():
  """创建用户""" 
  data = request.get_json() # 获取请求中的JSON数据
  name = data.get('name')
  age = data.get('age')
  email = data.get('email')

  if not name or not email:
    return jsonify({'error': '用户名和邮箱不能为空'}), 400 # 400 - Bad Request 客户端请求的语法错误

  conn = get_db_connection()
  cursor = conn.cursor()
  cursor.execute('INSERT INTO users (name, age, email) VALUES (?, ?, ?)', (name, age, email))
  conn.commit()
  conn.close()
  # 创建成功后 要更新数据库 要刷新一下
  # 刷新数据库
  init_db()

  return jsonify({'message': '用户创建成功'}), 201 # 201 - Created 资源创建成功


# 物理删除：直接从数据库中删除指定的记录 从数据库中删除
# 通常实际开发中 删除接口不会使用DELETE方法 而是使用POST方法
# 某些防火墙/代理会拦截DELETE请求
# 一些HTTP客户端库处理DELETE比较麻烦
@app.route('/api/delete_user/<int:user_id>', methods=['POST'])
def delete_user(user_id):
  """删除用户"""
  conn = get_db_connection()
  cursor = conn.cursor()

  # WHERE id = ? - 条件：只删除id等于指定值的用户
  # (user_id,) - 参数元组，替换SQL中的?占位符
  # 注意：(user_id,)中的逗号很重要，表示这是单元素元组，否则会被解释为整数
  cursor.execute('DELETE FROM users WHERE id = ?', (user_id,))
  conn.commit()
  conn.close()

  # 刷新数据库
  init_db()

  return jsonify({'message': '用户删除成功'}), 200 # 200 - OK 请求成功

# 逻辑删除：通过添加一个状态字段（如is_deleted），将记录标记为已删除，而不是实际删除
# 逻辑删除的优势：
# 1. 保留数据历史：可以查询出所有用户的历史记录，包括已删除的记录
# 2. 避免数据丢失：如果发生错误或恶意删除，数据可以恢复
# 3. 支持数据恢复：如果需要恢复已删除的记录，只需要更新状态字段即可
@app.route('/api/logical_delete_user/<int:user_id>', methods=['POST'])
def logical_delete_user(user_id):
  """逻辑删除用户"""
  conn = get_db_connection()
  cursor = conn.cursor()

  # SET is_deleted = 1 - 将is_deleted字段设置为1（表示已删除）
  cursor.execute('UPDATE users SET is_deleted = 1 WHERE id = ?', (user_id,))
  conn.commit()
  conn.close()

  return jsonify({'message': '用户逻辑删除成功'}), 200 # 200 - OK 请求成功


# 更新用户信息
@app.route('/api/update_user/<int:user_id>', methods=['POST'])
def update_user(user_id):
  """更新用户信息"""
  data = request.get_json()
  name = data.get('name')
  age = data.get('age')
  email = data.get('email')

  if not name or not email:
    return jsonify({'error': '用户名和邮箱不能为空'}), 400

  conn = get_db_connection()
  cursor = conn.cursor()
  cursor.execute('UPDATE users SET name = ?, age = ?, email = ? WHERE id = ?', (name, age, email, user_id))
  conn.commit()
  conn.close()

  # 刷新数据库
  init_db()

  return jsonify({'message': '用户更新成功'}), 200 # 200 - OK 请求成功

# # 启动执行器
# @app.on_event("startup") # on_event() - 注册一个事件，在应用启动时执行
# async def startup(): # 在应用启动时执行
#   print("应用启动时执行")
#   # init_db() # 初始化数据库和表结构

@app.before_request
def initialize():
  """初始化数据库和表结构"""
  print("初始化数据库和表结构")
  # init_db() # 初始化数据库和表结构



# python程序的入口点控制
# Python的特殊判断语句，用于判断当前模块是被直接运行还是被导入
if __name__ == '__main__':
  init_db() # 初始化数据库和表结构
  app.run(debug=True, port=5000) # 启动Flask应用 开启调试模式 监听端口5000

